/********************************************************************

Write Date: 2011/1/27
Author: Deng Nianchen
>>>> Implement general functions of a smart pointer.

Modify Date: 2011/3/22
Author: Deng Nianchen
>>>> Add cvt() function to support type convertion.
>>>> Add to OOPUtils namespace.
>>>> Use OOPException as exception framework.

Modify Date: 2011/03/24
Author: Deng Nianchen
>>>> Remove support for array pointer. (I think it is unnecessary)

Modify Date: 2011/06/02
Author: Deng Nianchen
>>>> Split Ptr to two classes: HeapPtr and OOPPtr. See HeapPtr.hpp 
     and OOPPtr.hpp for detail. Now this file contains only the common
     implementation of HeapPtr and OOPPtr and named PtrBase.
>>>> Add an exception TypeConvertFailException.
>>>> Changes in exceptions follow the change of OOPException.

Modify Date: 2011/07/16
Author: Deng Nianchen
>>>> Move class PtrException and its children to PtrExceptions.hpp

*********************************************************************/
#ifndef PTR_BASE_HPP
#define PTR_BASE_HPP
#include "OOPUtilsGlobal.hpp"
#include "CommonExceptions.hpp"
#include "PtrExceptions.hpp"
#include "OOPObject.h"


_OOPUTILS_BEGIN




/**************************************************************************************************
 * <summary> Purpose: The base class of HeapPtr and OOPPtr. Contains common
 * 					 implementation of smart ptr such as pointer operator 
 * 					 and dereference operator. </summary>
 * 
 * <remarks>  Deng Nianchen, 2011/6/2. </remarks>
 **************************************************************************************************/

template< class _Ty >
class PtrBase : public OOPObject
{

protected:

    _Ty * __pObj;

public:

    PtrBase (_Ty * newPtr);

    virtual ~PtrBase ();



    _Ty * operator-> () throw (NullPtrException &);

    const _Ty * operator-> () const throw (NullPtrException &);

    _Ty & operator* () throw (NullPtrException &);

    const _Ty & operator* () const throw (NullPtrException &);

    operator _Ty * ();

    operator const _Ty * () const;

};



/************************************************************************/
/* Constructors & Destructor                                            */
/************************************************************************/



template< class _Ty >
PtrBase< _Ty >::PtrBase (_Ty * const newPtr) : __pObj (newPtr) {}



template< class _Ty >
PtrBase< _Ty >::~PtrBase ()
{
  __pObj = NULL;
}



/************************************************************************/
/* Object access functions                                              */
/************************************************************************/



template< class _Ty >
_Ty * OOPUtils::PtrBase<_Ty>::operator-> () throw (NullPtrException &)
{
    if (__pObj == NULL)
        OOPTHROW (NullPtrException);
    return __pObj;
}



template< class _Ty >
const _Ty * OOPUtils::PtrBase<_Ty>::operator-> () const
        throw (NullPtrException &)
{
    if (__pObj == NULL)
        OOPTHROW (NullPtrException);
    return __pObj;
}



template< class _Ty >
_Ty & OOPUtils::PtrBase<_Ty>::operator* () throw (NullPtrException &)
{
    if (__pObj == NULL)
        OOPTHROW (NullPtrException);
    return *__pObj;
}



template< class _Ty >
const _Ty & OOPUtils::PtrBase<_Ty>::operator* () const
        throw (NullPtrException &)
{
    if (__pObj == NULL)
        OOPTHROW (NullPtrException);
    return *__pObj;
}



template< class _Ty >
OOPUtils::PtrBase<_Ty>::operator _Ty * ()
{
    return __pObj;
}



template< class _Ty >
OOPUtils::PtrBase<_Ty>::operator const _Ty * () const
{
    return __pObj;
}



_OOPUTILS_END



#endif